﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.FxCop.Sdk;
using EnvDTE80;
using EnvDTE;

namespace Common
{
    public static class Rotinas
    {
        public static ClassNode CheckClass(ClassNode classnode, string baseClass)
        {
            ClassNode currentClass = classnode;
            int i = 0;
            int totalNiveis = 3;

            while (!currentClass.BaseClass.Name.Name.Equals(baseClass) &&
                !currentClass.BaseClass.Name.Name.Equals("Object") && i < totalNiveis)
            {
                currentClass = currentClass.BaseClass;
                i++;
            }

            return currentClass;
        }

        public static bool CheckBase(ClassNode classnode, string baseName)
        {
            ClassNode currentClass = CheckClass(classnode, baseName);

            if (!currentClass.BaseClass.Name.Name.Equals(baseName))
                return false;
            else
                return true;
        }

        public static bool CheckClassInheritance(ClassNode classnode, Type type)
        {
            bool retorno = false;
            ClassNode currentClass = classnode;

            while (currentClass!=null)
            {
                if (currentClass.GetFullUnmangledNameWithoutTypeParameters() == type.FullName)
                {
                    retorno = true;
                    break;
                }

                currentClass = currentClass.BaseClass;
            }

            return retorno;
        }

        public static bool CheckClassInheritance(CodeClass2 classnode, Type type)
        {
            bool retorno = false;
            CodeElement item = null;
            Type typeBase;
            int index;
            int quantidadeParametros;
            string fullNameNonGeneric;

            if (classnode.IsGeneric
                && (type.IsGenericType 
                    || type.IsGenericTypeDefinition))
            {
                typeBase = type.GetGenericTypeDefinition();
                index = classnode.FullName.IndexOf("<");

                if (index > -1)
                {
                    quantidadeParametros = classnode.FullName.Substring(index).Split(',').Length;
                    fullNameNonGeneric = String.Concat(classnode.FullName.Substring(0, index), "`", quantidadeParametros);

                    if (fullNameNonGeneric == typeBase.FullName)
                    {
                        retorno = true;
                    }
                }
            }
            else if (classnode.FullName == type.FullName)
            {
                retorno = true;
            }

            if (!retorno)
            {
                for (int i = 1; i <= classnode.Bases.Count; i++)
                {
                    item = classnode.Bases.Item(i);
                    
                    if(item.Kind == vsCMElement.vsCMElementClass)
                    {
                        retorno = CheckClassInheritance((CodeClass2)item, type);

                        if (retorno)
                            break;
                    }
                }
            }

            return retorno;
        }

        public static bool CheckClassInheritance(CodeClass2 classnode, params Type[] types)
        {
            bool retorno = false;

            foreach (Type type in types)
            {
                retorno = CheckClassInheritance(classnode, type);

                if (retorno)
                    break;
            }

            return retorno;
        }

        public static bool CheckInterfaceInheritance(CodeClass2 classnode, Type type)
        {
            bool retorno = false;
            CodeInterface inter = null;
            CodeClass2 classeBase = null;

            for (int i = 1; i <= classnode.ImplementedInterfaces.Count; i++)
            {
                inter = (CodeInterface)classnode.ImplementedInterfaces.Item(i);

                if (CheckInterfaceInheritance(inter, type))
                {
                    retorno = true;
                    break;
                }
            }

            if (!retorno)
            {
                for (int i = 1; i <= classnode.Bases.Count; i++)
                {
                    classeBase = (CodeClass2)classnode.Bases.Item(i);
                    retorno = CheckInterfaceInheritance(classeBase, type);

                    if (retorno)
                        break;
                }
            }

            return retorno;
        }


        public static bool CheckInterfaceInheritance(CodeClass2 classnode, params Type[] types)
        {
            bool retorno = false;
            bool breakLoop = false;
            CodeInterface inter = null;
            CodeClass2 classeBase = null;

            foreach (Type type in types)
            {
                for (int i = 1; i <= classnode.ImplementedInterfaces.Count; i++)
                {
                    inter = (CodeInterface)classnode.ImplementedInterfaces.Item(i);

                    if (CheckInterfaceInheritance(inter, type))
                    {
                        retorno = true;
                        breakLoop = true;
                        break;
                    }
                }

                if (!retorno)
                {
                    for (int i = 1; i <= classnode.Bases.Count; i++)
                    {
                        classeBase = (CodeClass2)classnode.Bases.Item(i);
                        retorno = CheckInterfaceInheritance(classeBase, type);

                        if (retorno)
                        {
                            breakLoop = true;
                            break;
                        }
                    }
                }

                if (breakLoop)
                    break;
            }

            return retorno;
        }

        public static bool CheckInterfaceInheritance(CodeInterface interfacenode, Type type)
        {
            bool retorno = false;
            Type typeBase;
            int index;
            int quantidadeParametros;
            string fullNameNonGeneric;

            if (interfacenode.FullName == type.FullName)
            {
                retorno = true;
            }
            else if (type.IsGenericType
                || type.IsGenericTypeDefinition)
            {
                typeBase = type.GetGenericTypeDefinition();
                index = interfacenode.FullName.IndexOf("<");
                
                if (index > -1)
                {
                    quantidadeParametros = interfacenode.FullName.Substring(index).Split(',').Length;
                    fullNameNonGeneric = String.Concat(interfacenode.FullName.Substring(0, index), "`", quantidadeParametros);

                    if (fullNameNonGeneric == typeBase.FullName)
                    {
                        retorno = true;
                    }
                }
            }

            if(!retorno)
            {
                for (int i = 1; i <= interfacenode.Bases.Count; i++)
                {
                    if (CheckInterfaceInheritance((CodeInterface)interfacenode.Bases.Item(i), type))
                    {
                        retorno = true;
                        break;
                    }
                }
            }

            return retorno;
        }

        public static String GetTextNoComent(String text)
        {
            String textResult = string.Empty;
            String textComment = string.Empty;

            bool isCommentLine = false;
            bool isCommentBlock = false;

            if (text.Contains(@"/*") || text.Contains(@"//"))
            {
                foreach (char chr in text.ToCharArray())
                {
                    if (!isCommentLine && !isCommentBlock)
                    {
                        textResult += chr;

                        if (textResult.EndsWith(@"/*"))
                        {
                            isCommentBlock = true;
                            textResult = textResult.Replace(@"/*", "");
                        }
                        else if (textResult.EndsWith(@"//"))
                        {
                            isCommentLine = true;
                            textResult = textResult.Replace(@"//", "");
                        }
                    }
                    else
                    {
                        textComment += chr;

                        if (textComment.EndsWith(@"*/"))
                        {
                            isCommentBlock = false;
                            textComment = string.Empty;
                        }
                        else if (isCommentLine && textComment.EndsWith(Environment.NewLine))
                        {
                            isCommentLine = false;
                            textComment = string.Empty;
                            textResult += Environment.NewLine;
                        }
                    }
                }
            }
            else
            {
                textResult = text;
            }

            return textResult;
        }
    }
}